package com.api.project.service.impl;

import com.api.apicommon.model.entity.InterfaceInfo;
import com.api.apicommon.model.entity.UserInterfaceInfo;
import com.api.project.common.ErrorCode;
import com.api.project.exception.BusinessException;
import com.api.project.mapper.UserInterfaceInfoMapper;
import com.api.project.service.InterfaceInfoService;
import com.api.project.service.UserInterfaceInfoService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * 用户接口信息Service实现类
 */
@Service
public class UserInterfaceInfoServiceImpl extends ServiceImpl<UserInterfaceInfoMapper, UserInterfaceInfo>
        implements UserInterfaceInfoService {
    @Resource
    private InterfaceInfoService interfaceInfoService;

    @Resource
    private RedissonClient redissonClient;

    @Override
    public void validUserInterfaceInfo(UserInterfaceInfo userInterfaceInfo, boolean add) {

        if (userInterfaceInfo == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        // 创建时，所有参数必须非空
        if (add) {
            if (userInterfaceInfo.getInterfaceInfoId() <= 0 || userInterfaceInfo.getUserId() <= 0) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户或接口不存在");
            }
        }


        if (userInterfaceInfo.getLeftNum() < 0 || userInterfaceInfo.getTotalNum() < 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "剩余调用次数或总调用次数不能小于0");
        }
    }

    @Override
    @Transactional(isolation= Isolation.REPEATABLE_READ)
    public boolean invokeCount(long interfaceInfoId, long userId) {
        //校验参数
        if (interfaceInfoId <= 0 || userId <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户或接口不存在");
        }
        InterfaceInfo interfaceInfo = interfaceInfoService.getById(interfaceInfoId);
        if (interfaceInfo == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "接口不存在");
        }

        //更新用户接口信息
        UpdateWrapper<UserInterfaceInfo> userInterfaceInfoUpdateWrapper = new UpdateWrapper<>();
        userInterfaceInfoUpdateWrapper.eq("interfaceInfoId",interfaceInfoId);
        userInterfaceInfoUpdateWrapper.eq("userId",userId);
        //更新剩余调用次数,总调用次数,使totalNum+1,leftNum-1
        userInterfaceInfoUpdateWrapper.setSql("totalNum = totalNum + 1, leftNum = leftNum - 1");

        boolean update=false;
        //获取锁
        RLock lock = redissonClient.getLock("api:precachejob:invokeCount:lock");
        try{
            if (lock.tryLock(2000,1000, TimeUnit.MILLISECONDS)){
                update = this.update(userInterfaceInfoUpdateWrapper);
                if (!update) {
                    throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "更新用户接口信息失败");
                }
            }
        } catch (InterruptedException e) {
            System.out.println(e.getMessage());
            throw new RuntimeException(e);
        }finally {
            //释放锁
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }

        }

        return update;
    }

    @Override
    @Transactional(isolation= Isolation.REPEATABLE_READ)
    public UserInterfaceInfo getLeftNum(long interfaceInfoId, long userId) {
        if (interfaceInfoId <= 0 || userId <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户或接口不存在");
        }
        UserInterfaceInfo userInterfaceInfo = this.getOne(new QueryWrapper<UserInterfaceInfo>()
               .eq("interfaceInfoId", interfaceInfoId)
               .eq("userId", userId));
        if (userInterfaceInfo == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "用户接口信息不存在");
        }
        return userInterfaceInfo;
    }
}




